import ui_tcpclient
from PyQt5.QtWidgets import QWidget,QMessageBox,QApplication
from PyQt5.QtNetwork import QTcpSocket,QHostAddress,QAbstractSocket
from PyQt5.QtCore import QDataStream,QTime,QFile,QByteArray,QIODevice

class TcpClient(ui_tcpclient.Ui_Form,QWidget):
    def __init__(self):
        super(TcpClient, self).__init__()
        self.ui=ui_tcpclient.Ui_Form()
        self.ui.setupUi(self)

        self.tcpClient = QTcpSocket(self)
        self.bytesReceived = 0
        #self.bytesToReceive = 0
        self.TotalBytes = 0
        self.fileNameSize = 0
        self.fileName = ""
        self.ui.progressBar.reset()

        self.hostAddress = QHostAddress()
        self.inBlock = QByteArray()
        self.time = QTime()
        self.tcpPort = 6666

        self.tcpClient.readyRead.connect(self.readMessage)
        self.tcpClient.error.connect(self.displayError)
        self.ui.tcpClientCancleBtn.clicked.connect(self.cancleBtn)
        self.ui.tcpClientCloseBtn.clicked.connect(self.closeBtn)


    #设置文件名
    def setFileName(self,fileName):
        self.localFile = QFile(fileName)

    #设置地址
    def setHostAddress(self,address):
        self.hostAddress = address
        self.newConnect()

    #创建新连接
    def newConnect(self):
        self.blockSize = 0;
        self.tcpClient.abort()
        self.tcpClient.connectToHost(self.hostAddress,self.tcpPort)
        self.time.start()

    #读取消息
    def readMessage(self):

        inStream = QDataStream(self.tcpClient)
        inStream.setVersion(QDataStream.Qt_4_7)
        useTime = self.time.elapsed()

        if self.bytesReceived <= 16:

            if self.tcpClient.bytesAvailable()>=16 and self.fileNameSize == 0 :
                self.TotalBytes=inStream.readInt64()
                self.fileNameSize = inStream.readInt64()
                self.bytesReceived +=16

            if self.tcpClient.bytesAvailable() >= self.fileNameSize and\
                    self.fileNameSize != 0:

                self.fileName = inStream.readQString()
                self.bytesReceived += self.fileNameSize
                if not self.localFile.open(QIODevice.WriteOnly):
                    QMessageBox.warning(self,"应用程序","无法读取文件{}\n{}.".format
                    (self.fileName,self.localFile.errorString()))
                    return
                else :
                    return

        if self.bytesReceived < self.TotalBytes :
            self.bytesReceived += self.tcpClient.bytesAvailable()
            self.inBlock = self.tcpClient.readAll()
            self.localFile.write(self.inBlock)
            self.inBlock.resize(0)

        self.ui.progressBar.setMaximum(self.TotalBytes)
        self.ui.progressBar.setValue(self.bytesReceived)

        speed = self.bytesReceived / useTime
        format1 = self.bytesReceived/(1024*1024)
        format2 = speed*1000/(1024*1024)
        format3 = self.TotalBytes / (1024 * 1024)
        format4 = useTime/1000
        format5 = self.TotalBytes/speed/1000 - useTime/1000
        self.ui.tcpClientStatusLabel.setText("已接收{:.0f}MB ({:.2f}MB/S)"
            "\n共{:.0f}MB 已用时:{:.2f}秒\n估计剩余时间：""{:.2f}秒".format(format1,format2,format3,format4,format5))

        if self.bytesReceived == self.TotalBytes:
            self.localFile.close()
            self.tcpClient.close()
            self.ui.tcpClientStatusLabel.setText("接收文件{}完毕".format(self.fileName))


    #错误处理
    def displayError(self,socketError):
        if socketError == QAbstractSocket.RemoteHostClosedError:
            pass
        else:
            print(self.tcpClient.errorString())

    #取消按钮
    def cancleBtn(self):
        self.tcpClient.abort()
        if self.localFile.isOpen() :
            self.localFile.close()

    #关闭按钮
    def closeBtn(self):
        self.tcpClient.abort()

        if self.localFile.isOpen() :
            self.localFile.close()
        self.close()

    #关闭事件
    def closeEvent(self, QCloseEvent):
        self.closeBtn()

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    win = TcpClient()
    win.show()
    sys.exit(app.exec_())